package com.gkh.sqlparser;

import java.util.List;

public abstract class Token {

	// Token types
	public static int TOKEN_WORD = 1; // Keyword or unquoted identifier (will be refined later)
	public static int TOKEN_KEYWORD = 2; // Keyword (part of language, not only reserved words)
	public static int TOKEN_IDENT = 3; // Identifier (quoted, unquoted, qualified multi-part)
	public static int TOKEN_SYMBOL = 4; // Single char symbol
	public static int TOKEN_NUMBER = 5; // Number
	public static int TOKEN_STRING = 6; // Quoted string
	public static int TOKEN_COMMENT = 7; // Comment
	public static int TOKEN_BOM = 8; // UTF byte order mark
	public static int TOKEN_FUNCTION = 9; // Function
	public static int TOKEN_STATEMENT = 10; // Statement

	// Token subtype
	public static int TOKEN_SUB_COLUMN_NAME = 1; // Column name
	public static int TOKEN_SUB_IDENT_SEQNEXTVAL = 2; // Sequence nextval (ident.nextval)
	public static int TOKEN_SUB_FUNC_STRING = 3; // String function

	// Token data type
	public static int TOKEN_DT_DATETIME = 1; // Date and time
	public static int TOKEN_DT_STRING = 2; // String
	public static int TOKEN_DT_NUMBER = 3; // Number
	public static int TOKEN_DT_INTERVAL = 4; // Interval
	public static int TOKEN_DT_UDT = 5; // User-defined data type

	// Token data subtype
	public static int TOKEN_DT2_DATETIME = 1; // Date and time
	public static int TOKEN_DT2_DATETIME_SEC = 2; // Date and time up to seconds
	public static int TOKEN_DT2_DATE = 3; // Date only
	public static int TOKEN_DT2_TIME = 4; // Time only
	public static int TOKEN_DT2_INT = 5; // Integer
	public static int TOKEN_DT2_INTVL_MON = 6; // Month interval
	public static int TOKEN_DT2_INTVL_DAY = 7; // Day interval
	public static int TOKEN_DT2_INTVL_MIN = 8; // Minute interval
	public static int TOKEN_DT2_INTVL_SEC = 9; // Second interval
	public static int TOKEN_DT2_BOOL = 10; // Boolean value
	public static int TOKEN_DT2_UDT_TAB_SCALAR = 11; // UDT Table of scalar values

	// Token flags
	public static int TOKEN_REMOVED = 0x1;
	public static int TOKEN_INSERTED = 0x2;

	// Token type
	public char type;
	// Token target type (was function, converted to statement i.e.)
	public char t_type;

	public char subtype;

	// Token data type (Column type, function return value)
	public char data_type;
	public char data_subtype;

	// Resolved data type for columns
	public char[] datatype_meta;

	Token table;

	// Can contain NULL (function can return null)
	public boolean nullable;

	// Single char token data
	public char chr;
	public char wchr;

	// String data
	public char[] str;
	public char[] wstr;

	// Target values
	public char[] t_str;
	public char[] t_wstr;

	// Length of string data (0 for single char)
	int len;
	int t_len;

	// Token flags
	int flags;

	// Conversion notes associated with the token
	char[] notes_str;

	// Number of input bytes remain after token
	int remain_size;
	// Pointer to the buffer right after token
	char[] next_start;

	// Source value was allocated for the token, and needs to be deleted in
	// destructor
	boolean source_allocated;

	// Line in the source code where the token appears
	int line;

	// Open and close token for functions
	Token open;
	Token close;

	Token prev;
	Token next;

	// Constructor/destructor
	public Token() {
		type = 0;
		subtype = 0;
		t_type = 0;
		data_type = 0;
		data_subtype = 0;
		datatype_meta = null;
		table = null;
		nullable = true;

		chr = 0;
		wchr = 0;
		str = null;
		wstr = null;

		t_str = null;
		t_wstr = null;
		t_len = 0;

		len = 0;
		flags = 0;

		notes_str = null;

		remain_size = 0;
		next_start = null;
		line = 0;
		source_allocated = false;

		open = null;
		close = null;

		prev = null;
		next = null;
	}

	// Get a copy of token
	Token GetCopy(Token source) {
		if(source == null)
			return null;

		Token token = new Token();
		token = source;

		token.prev = null;
		token.next = null;

		// Reallocate source if space is not in place as the original token can be removed later
		if(source.source_allocated)
		{
			if(source.str != null)
				token.str = Str::GetCopy(source->str, source->len);
		}

		// Reallocate target values to separate buffers if set
		if(source->t_len != 0)
		{
			if(source->t_str != NULL)
				token->t_str = Str::GetCopy(source->t_str, source->t_len);
		}

		return token;
	}

	// Compare token value with the specified word or char
	abstract boolean Compare(char[] word, char[] w_word, int len);

	abstract boolean Compare(char[] word, char[] w_word, int start, int len);

	abstract boolean Compare(char ch, char wch);

	abstract boolean Compare(char ch, char wch, int start);

	abstract boolean Compare(Token token, char[] word, char[] w_word, int len);

	abstract boolean Compare(Token token, char[] word, char[] w_word, int start, int len);

	abstract boolean CompareCS(Token token, char[] word, char[] w_word, int start, int len);

	abstract boolean Compare(Token token, char ch, char wch);

	abstract boolean Compare(Token token, char ch, char wch, int start);

	abstract boolean Compare(Token first, Token second);

	abstract boolean Compare(Token first, Token second, int len);

	abstract boolean Compare(Token first, TokenStr second);

	abstract boolean CompareTarget(Token token, char[] word, char[] w_word, int len);

	abstract boolean IsNumeric();

	abstract boolean IsNumericInString();

	abstract boolean IsSingleChar();

	abstract boolean IsBlank();

	int IsRemoved() {
		return flags & TOKEN_REMOVED;
	}

	boolean IsTargetSet() {
		return (t_len > 0) ? true : false;
	}

	abstract boolean IsBlank(Token token);

	// Change the token value
	abstract void Change(Token token, char[] new_str, char[] new_wstr, int len, Token format);

	abstract void Change(Token token, int value);

	abstract void Change(Token token, Token values);

	abstract void ChangeNoFormat(Token token, char[] new_str, char[] new_wstr, int len);

	abstract void ChangeNoFormat(Token token, TokenStr tstr);

	abstract void ChangeNoFormat(Token token, Token source, int start, int len);

	// Replace the token value with spaces to preserve indent
	abstract void ReplaceWithSpaces(Token token);

	// Set Removed flag for the token
	abstract void Remove(Token token, boolean remove_spaces_before);

	abstract void Remove(Token from, Token last);

	// Get the target length of the token
	abstract int GetTargetLength();

	// Remove the current target value
	abstract void ClearTarget(Token token);

	// Append data to the string
	abstract void AppendTarget(char[] string, int[] cur_len);

	// Format target value case
	abstract void FormatTargetValue(Token token, Token format);

	// Skip blanks, tabs and newlines
	abstract Token SkipSpaces(Token token);

	// Get value as int
	abstract int GetInt();

	abstract int GetInt(int start, int len);

};
